/*	Copyright 2007 - Xavier Baro (xbaro@cvc.uab.cat)

	This file is part of eapmlib.

    Eapmlib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or any 
	later version.

    Eapmlib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
/*! \file Chromosome.h
\brief Chromosome class header
\author Xavier Bar Sol

This file contains the definition of the chromosome class. This class containt all the
information of an instance of a certain model. The data can be stored using different
representations.
*/
#ifndef __CHROMOSOME_H__
#define __CHROMOSOME_H__

#include "EvolutiveLib.h"
#include <iostream>
#include <string>
#include "VarSet.h"

using namespace std;
using namespace NBE;

namespace Evolutive {

	//! Defines the codification method for the chromosomes
	enum EVOLUTIVELIB_API CODING_METHOD {CODE_BINARY,CODE_GRAY,CODE_DECIMAL_INT,CODE_DECIMAL_DBL};

	//! Class to encode the chromosomes.
	class EVOLUTIVELIB_API CChromosome
	{
		//! Methods
	public:
		//! Default constructor		
		CChromosome(void);

		//! Copy constructor
		CChromosome(const CChromosome &C);
 
		//! Default destructor
		virtual ~CChromosome(void);
		
		//! Sets the number of fields and their description
		void SetFields(int NumFields,int *NumBits);

		//! Set codifying method
		void SetCode(CODING_METHOD Method);

		//! Get the codifying method
		CODING_METHOD GetCodingMethod(void);

		//! Generates a new chromosome from a probability distribution
		void Generate(double *ProbDist);	
		void Generate(void);

		//! Returns a printable representation for the chromosome
		const string ToString(void);	

		//! Returns a pointer to the bitstring
		unsigned char *GetBitStringPtr(void);

		//! Returns a pointer to the decimal representation
		unsigned int *GetIntStringPtr(void);

		//! Returns a pointer to the double representation
		double *GetDblStringPtr(void);

		//! Apply a Uniform mutation with probability Prob
		void UniformMutation(double Prob);

		//! Overload the assignment operator
		CChromosome& operator=( const CChromosome& C );

		//! Overload the equal and different operators
		bool operator==(CChromosome C);
		bool operator!=(CChromosome C);

		//! Returns the number of bits
		int GetNumBits(void);

		//! Decode the chromosome
		void Decode();

		//! Codify the chromosome
		void Code();

		//! Return the number of fields
		int GetNumFields(void);

		//! Assign a value to the chromosome
		void SetDecValue(unsigned int Data[]);		
		void SetDecValue(double Data[]);

		//! Converts a double floating point number to a binary string
		static void Dbl2Bin(double Number,unsigned char *BitString,int NumBits);

		//! Decode a binary coded number to their original double format.
		static double Bin2Dbl(unsigned char *BitString,int NumBits);

		//! Converts a decimal number to a binary string
		static void Dec2Bin(unsigned int Number,unsigned char *BitString,int NumBits);	

		//! Decode a binary coded number to their original decimal format.
		static unsigned int Bin2Dec(unsigned char *BitString,int NumBits);

		//! Converts a gray coded string to a binary string
		static void Grayc2Bin(unsigned char *GrayString,unsigned char *BitString,int NumBits);		

		//! Converts a binary coded value to a gray coded
		static void Bin2Grayc(unsigned char *BitString,unsigned char *GrayString,int NumBits);

	private:
		//! Builds a string with the chromosome representation
		const string ToString(unsigned char *BitString);		
		const string ToString(unsigned int *DecBitString);	
		const string ToString(double *DblBitString);	

		//! Copy the contents of a given object
		void Clone(const CChromosome &C);
			
		//! Attributes
	private:
		//! Type of code used
		CODING_METHOD m_CodingMethod;

		//! Number of bits of the chromosome
		int m_Length;

		//! Bit string
		unsigned char *m_BitString;

		//! Bit string in binary representation
		unsigned char *m_BinBitString;

		//! Bit string in gray-code representation
		unsigned char *m_GrayBitString;

		//! Decimal representation for each field
		unsigned int *m_IntBitString;

		//! Double representation for each field
		double *m_DblBitString;

		//! Number of fields coded with the chromosome
		int m_NumFields;

		//! Fields description. (each position contains the number of bits for this field)
		int *m_FieldsDesc;		
	};	

	//! Instantiate a varset from a chromosome
	CChromosome& operator>>(CChromosome& in, VarSet& x);

	//! Instantiate a chromosome from a varset
	CChromosome* operator<<(CChromosome* in, VarSet& x);
}
	//! Generate the output of all the data of a certain chromosome
	EVOLUTIVELIB_API std::ostream& operator<<(std::ostream &stream, Evolutive::CChromosome C);

#endif // __CHROMOSOME_H__
